local Widget = require "widgets/widget" -- 引入基础 Widget 类
local ImageButton = require "widgets/imagebutton" -- 引入图片按钮 Widget
local Image = require "widgets/image" -- 引入图片 Widget
local TEMPLATES = require "widgets/redux/templates" -- 引入 Redux 风格的 Widget 模板

-- 定义 ScrollGridList 类，继承自 Widget
local ScrollGridList = Class(Widget, function(self, items_data, items_processfn, params) -- 构造函数，接收项目数据、项目处理函数和参数表
    Widget._ctor(self, "ScrollGridList") -- 调用父类 Widget 的构造函数，并设置 Widget 名称为 "ScrollGridList"

    self.items_processfn = items_processfn -- 存储用于处理单个项目数据的函数，允许外部定义如何格式化传入的数据,返回一个容器对象
    -- 格式化数据供apply_fn使用
    if self.items_processfn ~= nil then -- 检查是否存在项目处理函数
        self.items = self.items_processfn(items_data) -- 初始化处理后的项目数据表
    else
        self.items = items_data -- 如果没有处理函数，直接使用原始项目数据
    end

    -- items_processfn 的示例用法 (注释掉的代码)
    -- items_processfn = function (item)
    --     return {
    --         prefab = item.prefab,
    --         atlas = item.atlas or "images/hud.xml",
    --         normal = item.normal or "inv_slot.tex",
    --         focus = item.focus or "inv_slot.tex",
    --         tooltip = item.tooltip or STRINGS.NAMES[string.upper(item.prefab)] or item.prefab
    --     }
    -- end

    --默认参数设置
    if params.spacing == nil then -- 如果参数中未指定间距
        params.spacing = 0 -- 设置默认间距为 0
    end
    -- 准备传递给 TEMPLATES.ScrollingGrid 的参数表
    local params_data = {
        widget_width = (params.grid_width + params.spacing) or 70, -- 计算并设置每个网格项的宽度（包括间距），默认 70
        widget_height = (params.grid_height + params.spacing) or 70, -- 计算并设置每个网格项的高度（包括间距），默认 70
        num_visible_rows = params.rows or 5, -- 设置可见行数，默认 5
        num_columns = params.columns or 5, -- 设置列数，默认 5
        peek_height = params.peek_height or 0, -- 设置预览高度，默认 0 (不预览)
        peek_percent = params.peek_percent or 0, -- 设置预览百分比，默认 0 (不预览)(比peek_height更高的优先级)
        end_offset = params.end_offset or 1, -- 设置结束偏移量，默认 1
        scissor_pad = params.scissor_pad or 10, -- 设置水平剪裁填充量，默认 10
        -- 初始化创建网格项的函数 (item_ctor_fn)
        item_ctor_fn = params.item_ctor_fn or function(context, index) -- 如果外部未提供，则使用默认构造函数
            local w = Widget("grid-item-"..index) -- 创建一个基础 Widget 作为网格项容器
            w.btn = w:AddChild(ImageButton()) -- 在容器中添加一个 ImageButton
            return w -- 返回创建的网格项 Widget
        end,

        -- 更新网格项数据和交互的函数 (apply_fn)
        apply_fn = params.apply_fn or function(context, widget, data, index) -- 如果外部未提供，则使用默认应用函数
            if data then -- 如果当前索引有对应的数据
                widget.btn:SetTextures(data.atlas, data.normal, data.focus) -- 设置按钮的纹理 (图集, 普通状态, 聚焦状态)
                widget.btn:SetTooltip(data.tooltip) -- 设置按钮的提示文本
                widget.btn:SetOnClick(function() -- 设置按钮的点击事件回调
                    -- 点击回调函数
                    if data.onclick then -- 如果数据中定义了 onclick 回调
                        data.onclick(data.prefab) -- 执行定义的回调，并传入 prefab 名称
                    else
                        print("点击物品:", data.prefab) -- 否则，打印默认的点击信息
                    end
                end)
                widget.btn:Show() -- 显示按钮
            else
                widget.btn:Hide() -- 如果没有数据，则隐藏按钮
            end
        end,

        scrollbar_offset = params.scrollbar_offset or 20, -- 设置滚动条的水平偏移量，默认 20
        scrollbar_vertical_offset = params.scrollbar_vertical_offset or 0, -- 设置滚动条的垂直偏移量，默认 0
        scrollbar_height_offset = params.scrollbar_height_offset or -60, -- 设置滚动条的高度的变化值，默认-60(相对于滚动列表的高度减少60)

        scrollbar_style = params.scrollbar_style or nil, -- 滚动条样式，默认为 nil (使用默认样式)
        -- 示例样式
        -- scrollbar_style = {
        --     atlas = "images/my_ui/my_ui.xml",
        --     up_arrow = "scrollbar_arrow_up.tex",
        --     up_arrow_scale = 0.3,
        --     down_arrow = "scrollbar_arrow_down.tex",
        --     down_arrow_scale = 0.3,
        --     bar = "scrollbar_bar.tex",
        --     bar_scale = 0.3,
        --     bar_width = 20,
        --     bar_height = 260,
        --     handle = "scrollbar_handle.tex",
        --     handle_scale = 0.3,
        -- }
    }

    -- 创建滚动网格
    -- 使用 TEMPLATES.ScrollingGrid 创建滚动网格实例，并将其添加为子 Widget
    self.grid = self:AddChild(TEMPLATES.ScrollingGrid(self.items, params_data)) -- 传入处理后的项目数据和配置参数
    local scrollbar_pos = nil -- 初始化滚动条位置变量
    if self.grid then
        local scrollbar_pos = self.grid.scroll_bar_container:GetPosition() -- 获取滚动条容器的位置
        if params.scrollbar_vertical_offset then
            self.grid.scroll_bar_container:SetPosition(
                scrollbar_pos.x,
                scrollbar_pos.y + params.scrollbar_vertical_offset,
                scrollbar_pos.z
            ) -- 如果提供了垂直偏移量，则调整滚动条容器的位置
        end
    end
    -- 如果提供了滚动条样式参数 (scrollbar_style)，则进行自定义设置
    if self.grid and params.scrollbar_style then -- 检查 grid 是否成功创建且 scrollbar_style 是否存在
        -- 修改上箭头按钮样式
        if self.grid.up_button and params.scrollbar_style.up_arrow then -- 检查上箭头按钮和对应的样式参数是否存在
            self.grid.up_button:SetTextures(params.scrollbar_style.atlas, params.scrollbar_style.up_arrow) -- 设置上箭头按钮的纹理
            self.grid.up_button:SetScale(params.scrollbar_style.up_arrow_scale or 0.3) -- 设置上箭头按钮的缩放，默认为 0.3
        end

        -- 修改下箭头按钮样式
        if self.grid.down_button and params.scrollbar_style.down_arrow then -- 检查下箭头按钮和对应的样式参数是否存在
            self.grid.down_button:SetTextures(params.scrollbar_style.atlas, params.scrollbar_style.down_arrow) -- 设置下箭头按钮的纹理
            self.grid.down_button:SetScale(params.scrollbar_style.down_arrow_scale or 0.3) -- 设置下箭头按钮的缩放，默认为 0.3
        end

        -- 修改滚动条背景样式
        if self.grid.scroll_bar_line and params.scrollbar_style.bar then -- 检查滚动条背景和对应的样式参数是否存在
            self.grid.scroll_bar_line:SetTexture(params.scrollbar_style.atlas, params.scrollbar_style.bar) -- 设置滚动条背景的纹理
            if params.scrollbar_style.bar_scale then
                self.grid.scroll_bar_line:SetScale(params.scrollbar_style.bar_scale) -- 设置滚动条背景的缩放
            elseif params.scrollbar_style.bar_width and params.scrollbar_style.bar_height then
                self.grid.scroll_bar_line:ScaleToSize(
                    params.scrollbar_style.bar_width,
                    params.scrollbar_style.bar_height
                ) -- 设置滚动条背景的宽高
            end
        end

        -- 修改滚动条滑块样式
        if self.grid.position_marker and params.scrollbar_style.handle then -- 检查滚动条滑块和对应的样式参数是否存在
            -- 注意：position_marker 本身是 ImageButton，需要同时设置按钮纹理和内部 image 的纹理
            self.grid.position_marker:SetTextures(params.scrollbar_style.atlas, params.scrollbar_style.handle) -- 设置滑块按钮的纹理
            self.grid.position_marker.image:SetTexture(params.scrollbar_style.atlas, params.scrollbar_style.handle) -- 设置滑块内部 Image 的纹理
            self.grid.position_marker:SetScale(params.scrollbar_style.handle_scale or  0.3) -- 设置滑块的缩放，默认为 0.3
        end
    end
end) -- 构造函数结束

-- 添加复数网格数据，参数必须和建立的时候items_data同格式
-- 向现有的网格列表中添加新的项目数据
-- @param new_items table 包含新项目数据的表，其格式应与构造函数接收的 items_data 兼容
function ScrollGridList:AddGrids(new_items)
    if self.items_processfn ~= nil then
        table.insert(self.items, self.items_processfn(new_items)) -- 将处理后的项目添加到内部的 self.items 表中
    else
        table.insert(self.items, new_items) -- 如果没有处理函数，直接添加原始项目数据
        -- 注意：这里假设 new_items 是一个单个项目的表，如果是多个项目需要遍历添加
    end

    self.grid:SetItemsData(self.items) -- 更新底层 ScrollingGrid 的项目数据，这将触发 apply_fn 来刷新显示
end

-- 更新网格数据
-- 重置网格列表的数据，用新的项目数据完全替换旧数据
-- @param new_items table 包含新项目数据的表，其格式应与构造函数接收的 items_data 兼容
function ScrollGridList:ResetGrids(items_data)
    self.items = {}  -- 清空当前的内部项目数据表
    if self.items_processfn ~= nil then -- 检查是否存在项目处理函数
        self.items = self.items_processfn(items_data) -- 初始化处理后的项目数据表
    else
        self.items = items_data -- 如果没有处理函数，直接使用原始项目数据
    end
    self.grid:SetItemsData(self.items) -- 更新底层 ScrollingGrid 的项目数据，这将触发 apply_fn 来刷新显示
end

--暂时没有任何用处
-- 刷新网格视图，强制重新应用 apply_fn 到可见项目上
-- 注意：此方法直接调用底层 TrueScrollList 的 RefreshView，其具体效果可能取决于 TrueScrollList 的实现
function ScrollGridList:RefreshView()
    self.grid:RefreshView()  -- 调用底层 grid (即 ScrollingGrid/TrueScrollList) 的 RefreshView 方法
end

return ScrollGridList -- 返回 ScrollGridList 类，使其可以在其他地方被 require 和使用
